package customer.ejb.eaos;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import authentication.ejb.usermanagement.Group;
import authentication.ejb.usermanagement.User;
import model.Excursion;
import model.ExcursionPersTP;
import model.GetEntities;
import model.Hotel;
import model.Invitation;
import model.PersonalizedTP;
import model.PredefinedTP;
import common.Filter;
import common.IPredicate;
import common.OperationCallback;
import dtos.ExcursionPersTPDTO;
import dtos.HotelDTO;
import dtos.PersonalizedTPDTO;
import dtos.PredefinedTPDTO;
import dtos.UserDTO;

@Stateless
public class PersonalizedTPManagerEAO implements PersonalizedTPInterface{

	@PersistenceContext
	private EntityManager em;
	
	private String username;
	private int invitationID;
	private String mailAddress;
	
	private int id;
	
	public PersonalizedTPManagerEAO(){
		
	}
	
	@Override
	public PersonalizedTPDTO createPackage(int id, String userid) {
		PredefinedTP p = em.find(PredefinedTP.class, id);
		User user = em.find(User.class, userid);
		PredefinedTPDTO pdto = p.getDTO();
		PersonalizedTPDTO p2 = new PersonalizedTPDTO();
		p2.setExcursions(pdto.getExcursions());
		p2.setHotelBean(pdto.getHotelBean());
		p2.setMeanOfTransportation1(pdto.getMeanOfTransportation1());
		p2.setMeanOfTransportation2(pdto.getMeanOfTransportation2());
		p2.setUser(user.getUserDTO());
				
		return p2;
			

	}

	@Override
	public void savePersonalizedTP(PersonalizedTPDTO p, OperationCallback oc) {
		if(!p.isValid())
		{
			oc.onError(new IllegalArgumentException("Invalid personalized travel package."));
			return;
		}
		try
		{
			GetEntities ge = new GetEntities();
			PersonalizedTP newPersonalizedTP = ge.getPersonalizedTPEntity(p);
			
			em.persist(newPersonalizedTP);
			
			em.flush();
			em.refresh(newPersonalizedTP);
			oc.onSuccess("The personalized travel package has been created");
			id = newPersonalizedTP.getTravelID();
		}
		catch(Throwable t)
		{
			oc.onError(t);
		}
		
	}
	
	
	@Override
	public void savePersonalizedTP(PersonalizedTPDTO p, String username, OperationCallback oc) {
		User u = em.find(User.class, username);
		p.setUser(u.getUserDTO());
		if(!p.isValid())
		{
			oc.onError(new IllegalArgumentException("Invalid personalized travel package."));
			return;
		}
		try
		{
			GetEntities ge = new GetEntities();
			PersonalizedTP newPersonalizedTP = ge.getPersonalizedTPEntity(p);

			em.persist(newPersonalizedTP);			
			em.flush();
			em.refresh(newPersonalizedTP);
			oc.onSuccess("You joined the travel package");
			id = newPersonalizedTP.getTravelID();
		}
		catch(Throwable t)
		{
			oc.onError(t);
		}
		
	}
	

	@Override
	public Collection<PersonalizedTPDTO> getTravels(String username) {
		this.username = username;
		
		@SuppressWarnings("unchecked")
		List<PersonalizedTP> qres = em.createQuery("SELECT x FROM PersonalizedTP x").getResultList();
		Collection<PersonalizedTP> fres = Filter.filter(qres, isOK);
		Collection<PersonalizedTPDTO> res = new ArrayList<PersonalizedTPDTO>(fres.size());
		
		
		for(PersonalizedTP e : fres)
		{
			res.add(e.getDTO());
		}
		
		return res;
		
	}
	
	IPredicate<PersonalizedTP> isOK = new IPredicate<PersonalizedTP>() {
		public boolean apply(PersonalizedTP tp) {

	        return tp.belongsTo(username);
	    }

	};




	@Override
	public Collection<PersonalizedTPDTO> getPersonalizedInvitTP(String username) {
		this.username = username;
		
		@SuppressWarnings("unchecked")
		List<Invitation> qres = em.createQuery("SELECT x FROM Invitation x").getResultList();
		Collection<Invitation> fres = Filter.filter(qres, isReceivedBy);
		Collection<PersonalizedTPDTO> res = new ArrayList<PersonalizedTPDTO>(fres.size());
		
		
		for(Invitation i : fres)
		{
			res.add(i.getPersonalizedTp().getDTO());
		}
		
		return res;
	}
	
	IPredicate<Invitation> isReceivedBy = new IPredicate<Invitation>() {
		public boolean apply(Invitation i) {

	        return i.isInvited(username);
	    }

	};
	
	IPredicate<Invitation> correspondToID = new IPredicate<Invitation>() {
		public boolean apply(Invitation i) {

	        return i.correspondToID(mailAddress,invitationID);
	    }

	};

	@Override
	public void confirmTravel(PersonalizedTPDTO selectedTravel) {
		PersonalizedTP tp = em.find(PersonalizedTP.class, selectedTravel.getTravelID());
		tp.setConfirmed(true);
		em.merge(tp);
		
	}

	@Override
	public PersonalizedTPDTO getPersonalizedTP(String mailAddress,int invitationCode) {
		this.invitationID = invitationCode;
		this.mailAddress = mailAddress;
		
		@SuppressWarnings("unchecked")
		List<Invitation> qres = em.createQuery("SELECT x FROM Invitation x").getResultList();
		Collection<Invitation> fres = Filter.filter(qres, correspondToID);
		PersonalizedTPDTO res = null;
		
		for(Invitation i : fres)
		{
			res = i.getPersonalizedTp().getDTO();
		}
		
		return res;
	}

	@Override
	public void saveExcursionPersTP(ExcursionPersTPDTO e) {
		
		ExcursionPersTP exc = new ExcursionPersTP();
		exc.setDate(e.getDate());
		exc.setExcursion(em.find(Excursion.class, e.getExcursion().getExcursionID()));
		PersonalizedTP tp = em.find(PersonalizedTP.class, id);
		exc.setPersonalizedTp(tp);
		em.persist(exc);
		em.refresh(tp);

		em.flush();
		em.refresh(tp);

	}

	@Override
	public Collection<PersonalizedTPDTO> getAllPersonalizedTP() {
		@SuppressWarnings("unchecked")
		List<PersonalizedTP> qres = em.createQuery("SELECT x FROM PersonalizedTP x").getResultList();
		
		Collection<PersonalizedTPDTO> res = new ArrayList<PersonalizedTPDTO>(qres.size());
		
		
		for(PersonalizedTP e : qres)
		{
			res.add(e.getDTO());
		}
		
		return res;
		
	}

	@Override
	public void removePersTP(int travelID) {
		PersonalizedTP tp = em.find(PersonalizedTP.class, travelID);
		em.remove(tp);
		
	}




	
	


}
